/********************************************************************************
* @file    bsp_i2c.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-04-11
* @brief   NULL
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>

#include "cx32l003_hal.h"

#include "bsp_gpio.h"
#include "bsp_i2c.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Variables ---------------------------------------------------------*/
#if LS_I2C0_EN
// 定义IIC0信息句柄
static I2C_HandleTypeDef i2c0_handle_t = {
    .Instance        = I2C,
    .Init.master     = I2C_MASTER_MODE_ENABLE, // 主机模式使能
    .Init.slave      = I2C_SLAVE_MODE_DISABLE, // 从机模式禁止
    .Mode            = HAL_I2C_MODE_MASTER,    // 主机模式
    .Init.broadack   = I2C_BROAD_ACK_DISABLE,  // 广播地址应答禁止
    .Init.speedclock = LS_I2C0_SPEED_RATE,     // I2C传输速率
    .State           = HAL_I2C_STATE_RESET
};
#endif

/**
 * @brief  [初始化] IIC初始化
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @retval None
 */
void bsp_i2c_init(bsp_i2c_bus_t i2c_bus)
{
#if LS_I2C0_EN
    if (i2c_bus == I2C_BUS0)
    {
        __HAL_RCC_I2C_CLK_ENABLE();
        bsp_gpio_set_clk(GPIO_APBx, LS_I2C0_SDA_GPIO_CLK, true);
        bsp_gpio_set_clk(GPIO_APBx, LS_I2C0_SCL_GPIO_CLK, true);
        bsp_gpio_init_i2c(LS_I2C0_SCL_GPIO_PORT, LS_I2C0_SCL_PIN, GPIO_AF4_I2C_SCL);
        bsp_gpio_init_i2c(LS_I2C0_SDA_GPIO_PORT, LS_I2C0_SDA_PIN, GPIO_AF4_I2C_SDA);
        HAL_I2C_Init(&i2c0_handle_t);
    }
#endif
}

/**
 * @brief  [反初始化] IIC关闭时钟并复位引脚
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @retval None
 */
void bsp_i2c_deinit(bsp_i2c_bus_t i2c_bus)
{
#if LS_I2C0_EN
    if (i2c_bus == I2C_BUS0)
    {
        __HAL_RCC_I2C_CLK_DISABLE();
        bsp_gpio_deinit(LS_I2C0_SCL_GPIO_PORT, LS_I2C0_SCL_PIN);
        bsp_gpio_deinit(LS_I2C0_SDA_GPIO_PORT, LS_I2C0_SDA_PIN);
        HAL_I2C_DeInit(&i2c0_handle_t);
    }
#endif
}

/**
 * @brief  i2c读取一个字节
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  dev_addr: 器件地址
 * @param  reg_addr: 寄存器地址
 * @param  r_data: 欲发送的数据头指针
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_read_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t *r_data)
{
    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, &reg_addr, 1, r_data, 1);
#else
        return HAL_ERROR;
#endif
    }
    return HAL_ERROR;
}

/**
 * @brief  i2c读取多个字节
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  dev_addr: 器件地址
 * @param  w_data: txbuff头指针 数据格式：(reg_addr, w_data, w_data1, ...)
 * @param  w_size: txbuff长度
 * @param  r_data: rxbuff的头指针
 * @param  r_size: rxbuff的大小
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_read_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size, uint8_t *r_data, uint16_t r_size)
{
    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        return HAL_I2C_Master_Receive(&i2c0_handle_t, dev_addr, w_data, w_size, r_data, r_size);
#else
        return HAL_ERROR;
#endif
    }
    return HAL_ERROR;
}

/**
 * @brief  i2c写入一个字节
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  dev_addr: 器件地址
 * @param  reg_addr: 寄存器地址
 * @param  w_data: 需要写入的字节值
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_write_byte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t reg_addr, uint8_t w_data)
{
    uint8_t ret = HAL_OK;

    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        uint8_t data[2] = {reg_addr, w_data};
        ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, data, 2);
#else
        ret = HAL_ERROR;
#endif
    }
    else
    {
        ret = HAL_ERROR;
    }
    return ret;
}

/**
 * @brief  i2c写入多个字节
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  dev_addr: 器件地址
 * @param  w_data: txbuff头指针 数据格式：(reg_addr, w_data, w_data1, ...)
 * @param  w_size: txbuff长度
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_write_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size)
{
    uint8_t ret = HAL_OK;

    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        ret = HAL_I2C_Master_Transmit(&i2c0_handle_t, dev_addr, w_data, w_size);
#else
        ret = HAL_ERROR;
#endif
    }
    else
    {
        ret = HAL_ERROR;
    }
    return ret;
}

// ---------------------散装函数-----------------------------
/**
 * @brief  i2c写入多个字节且无停止信号(带起始信号和器件地址)
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  dev_addr: 器件地址
 * @param  w_data: txbuff头指针 数据格式：(reg_addr, w_data, w_data1, ...)
 * @param  w_size: txbuff长度
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_write_nbyte_nostop(bsp_i2c_bus_t i2c_bus, uint8_t dev_addr, uint8_t *w_data, uint16_t w_size)
{
    uint8_t ret = HAL_OK;

    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        ret = HAL_I2C_Master_Transmit_NOStop(&i2c0_handle_t, dev_addr, w_data, w_size);
#else
        ret = HAL_ERROR;
#endif
    }
    else
    {
        ret = HAL_ERROR;
    }
    return ret;
}

/**
 * @brief  i2c写入多个字节且无停止信号(不带起始信号和器件地址)
 * @note   必须配合[bsp_i2c_write_nbyte_nostop()]使用
 * @param  i2c_bus: IIC组号
 * @param  w_data: txbuff头指针 数据格式：(w_data, w_data1, ...)
 * @param  w_size: txbuff长度
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_send_nbyte(bsp_i2c_bus_t i2c_bus, uint8_t *w_data, uint16_t w_size)
{
    uint8_t ret = HAL_OK;
    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        uint16_t i = 0;
        uint32_t i2c_flag = 0XFF;
        HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag);
        while (i < w_size)
        {
            i2c_flag = 0XFF;
            HAL_I2C_Send_Byte(&i2c0_handle_t, w_data[i]);
            HAL_I2C_Wait_Flag(&i2c0_handle_t, &i2c_flag);
            if (i2c_flag != I2C_FLAG_MASTER_TX_DATA_ACK) // 0x00000028U
            {
                i2c0_handle_t.State = HAL_I2C_STATE_ERROR;
                i2c0_handle_t.ErrorCode = i2c0_handle_t.PreviousState;
                return HAL_ERROR;
            }
            i++;
        }
#else
        ret = HAL_ERROR;
#endif
    }
    else
    {
        ret = HAL_ERROR;
    }
    return ret;
}

/**
 * @brief  发送一个停止信号
 * @note   NULL
 * @param  i2c_bus: IIC组号
 * @param  state: false--清除中断标志位  true--不清除中断标记位
 * @retval 0--成功 1--失败
 */
uint8_t bsp_i2c_stop(bsp_i2c_bus_t i2c_bus, bool state)
{
    uint8_t ret = HAL_OK;

    if (i2c_bus == I2C_BUS0)
    {
#if LS_I2C0_EN
        HAL_I2C_Stop_Config(&i2c0_handle_t, (FunctionalState)true);
#else
        ret = HAL_ERROR;
#endif
    }
    else
    {
        ret = HAL_ERROR;
    }
    return ret;
}
